package com.ct.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ct.entity.enums.AdvanceApprovalEnum;
import com.ct.entity.enums.PageSize;
import com.ct.entity.enums.ReimbursementApprovalEnum;
import com.ct.entity.enums.TravelApprovalEnum;
import com.ct.entity.po.AdvanceApproval;
import com.ct.entity.po.Approval;
import com.ct.entity.po.Reimbursement;
import com.ct.entity.po.ReimbursementApprovalFi;
import com.ct.entity.po.ReimbursementApprovalMa;
import com.ct.entity.po.Travel;
import com.ct.entity.po.TravelApproval;
import com.ct.entity.po.User;
import com.ct.entity.query.AdvanceApprovalQuery;
import com.ct.entity.query.ApprovalQuery;
import com.ct.entity.query.ReimbursementApprovalFiQuery;
import com.ct.entity.query.ReimbursementApprovalMaQuery;
import com.ct.entity.query.SimplePage;
import com.ct.entity.query.TravelApprovalQuery;
import com.ct.entity.vo.PaginationResultVO;
import com.ct.entity.vo.ReimbursementVO;
import com.ct.entity.vo.TravelVO;
import com.ct.exception.BusinessException;
import com.ct.factory.AdvanceApprovalFactory;
import com.ct.factory.ReimbursementApprovalFiFactory;
import com.ct.factory.ReimbursementApprovalMaFactory;
import com.ct.factory.TravelApprovalFactory;
import com.ct.mappers.AdvanceApprovalMapper;
import com.ct.mappers.ApprovalMapper;
import com.ct.mappers.ReimbursementApprovalFiMapper;
import com.ct.mappers.ReimbursementApprovalMaMapper;
import com.ct.mappers.TravelApprovalMapper;
import com.ct.service.ApprovalService;
import com.ct.service.chain.ProcessorChain;
import com.ct.service.chain.ReimbursementMaProcessor;
import com.ct.service.chain.TravelProcessor;
import com.ct.service.client.ReimbursementClient;
import com.ct.service.client.TravelClient;
import com.ct.service.client.UserClient;
import com.ct.utils.CopyTools;
import com.ct.utils.StringTools;

import jakarta.annotation.Resource;

/**
 * 审批状态表 业务接口实现
 */
@Service("approvalService")
public class ApprovalServiceImpl implements ApprovalService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Resource
    private ApprovalMapper<Approval, ApprovalQuery> approvalMapper;

    @Resource
    private TravelClient travelClient;

    @Resource
    private UserClient userClient;

    @Resource
    private ReimbursementClient reimbursementClient;

    @Resource
    private TravelApprovalMapper<TravelApproval, TravelApprovalQuery> travelApprovalMapper;

    @Resource
    private ReimbursementApprovalMaMapper<ReimbursementApprovalMa, ReimbursementApprovalMaQuery> reimbursementApprovalMaMapper;

    @Resource
    private ReimbursementApprovalFiMapper<ReimbursementApprovalFi, ReimbursementApprovalFiQuery> reimbursementApprovalFiMapper;

    @Resource
    private AdvanceApprovalMapper<AdvanceApproval, AdvanceApprovalQuery> advanceApprovalMapper;

    /**
     * 根据条件查询列表
     */
    @Override
    public List<Approval> findListByParam(ApprovalQuery param) {
        return this.approvalMapper.selectList(param);
    }

    /**
     * 根据条件查询列表
     */
    @Override
    public Integer findCountByParam(ApprovalQuery param) {
        return this.approvalMapper.selectCount(param);
    }

    /**
     * 分页查询方法
     */
    @Override
    public PaginationResultVO<Approval> findListByPage(ApprovalQuery param) {
        int count = this.findCountByParam(param);
        int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

        SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
        param.setSimplePage(page);
        List<Approval> list = this.findListByParam(param);
        PaginationResultVO<Approval> result = new PaginationResultVO<>(count, page.getPageSize(), page.getPageNo(),
                page.getPageTotal(), list);
        return result;
    }

    /**
     * 新增
     */
    @Override
    public Integer add(Approval bean) {
        return this.approvalMapper.insert(bean);
    }

    /**
     * 批量新增
     */
    @Override
    public Integer addBatch(List<Approval> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.approvalMapper.insertBatch(listBean);
    }

    /**
     * 批量新增或者修改
     */
    @Override
    public Integer addOrUpdateBatch(List<Approval> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.approvalMapper.insertOrUpdateBatch(listBean);
    }

    /**
     * 多条件更新
     */
    @Override
    public Integer updateByParam(Approval bean, ApprovalQuery param) {
        StringTools.checkParam(param);
        return this.approvalMapper.updateByParam(bean, param);
    }

    /**
     * 多条件删除
     */
    @Override
    public Integer deleteByParam(ApprovalQuery param) {
        StringTools.checkParam(param);
        return this.approvalMapper.deleteByParam(param);
    }

    /**
     * 根据ApprovalId获取对象
     */
    @Override
    public Approval getApprovalByApprovalId(Integer approvalId) {
        return this.approvalMapper.selectByApprovalId(approvalId);
    }

    /**
     * 根据ApprovalId修改
     */
    @Override
    public Integer updateApprovalByApprovalId(Approval bean, Integer approvalId) {
        return this.approvalMapper.updateByApprovalId(bean, approvalId);
    }

    /**
     * 根据ApprovalId删除
     */
    @Override
    public Integer deleteApprovalByApprovalId(Integer approvalId) {
        return this.approvalMapper.deleteByApprovalId(approvalId);
    }

    /**
     * 获取出差申请信息
     * 
     * @param userId 工号
     * @return 出差申请信息列表
     */
    @Override
    public PaginationResultVO<TravelVO> getTravelApply(String userId, Integer pageNo, Integer pageSize) {
        List<TravelVO> travelVOList = new ArrayList<>();

        List<TravelApprovalEnum> approvalStatuses = List.of(
                TravelApprovalEnum.UNPROCESSED,
                TravelApprovalEnum.APPROVED,
                TravelApprovalEnum.REJECTED);

        for (TravelApprovalEnum status : approvalStatuses) {
            travelVOList.addAll(fetchTravelVOsByApprovalStatus(status));
        }

        // 去除自己的申请
        travelVOList.removeIf(travelVO -> travelVO.getUserId().equals(userId));

        int count = travelVOList.size();
        int start = (pageNo - 1) * pageSize;
        int end = start + pageSize;
        if (end > count) {
            end = count;
        }
        int totalPage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;

        PaginationResultVO<TravelVO> result = new PaginationResultVO<>(count, pageSize, pageNo, totalPage,
                travelVOList);

        return result;
    }

    private List<TravelVO> fetchTravelVOsByApprovalStatus(TravelApprovalEnum status) {
        List<TravelVO> travelVOList = new ArrayList<>();

        // 查询出差申请状态
        ApprovalQuery approvalQuery = new ApprovalQuery();
        approvalQuery.setTravelApproval(status.getType());

        List<Approval> approvalList = this.findListByParam(approvalQuery);
        Map<Integer, Approval> approvalMap = approvalList.stream()
                .collect(Collectors.toMap(Approval::getTravelId, approval -> approval));

        List<Integer> travelIdList = approvalList.stream().map(Approval::getTravelId).distinct().toList();

        if (travelIdList.isEmpty()) {
            return travelVOList;
        }

        // 获取出差申请和对应的用户信息
        List<Travel> travelList = this.travelClient.getAllTravelsByIdList(travelIdList);
        travelList.sort((o1, o2) -> o1.getApplyDate().compareTo(o2.getApplyDate()));

        List<String> userIdList = travelList.stream().map(Travel::getUserId).distinct().toList();

        List<User> userList = userClient.getAllUsersByIdList(userIdList);
        Map<String, User> userMap = userList.stream()
                .collect(Collectors.toMap(User::getUserId, user -> user));

        for (Travel travel : travelList) {
            TravelVO travelVO = CopyTools.copy(travel, TravelVO.class);

            travelVO.setTravelRejection(approvalMap.get(travel.getTravelId()).getTravelRejection());
            travelVO.setApprovalId(approvalMap.get(travel.getTravelId()).getApprovalId());

            travelVO.setTravelStatus(status.getType().toString());
            travelVO.setTravelStatusName(status.getDesc());

            User user = userMap.get(travel.getUserId());
            travelVO.setUserName(user.getName());
            travelVO.setUserPhone(user.getPhone());
            travelVO.setUserEmail(user.getEmail());
            travelVO.setPosition(user.getPosition());
            travelVO.setBudget(travelVO.getFoodCost().add(travelVO.getHotelCost()).add(travelVO.getTransportCost()));

            travelVOList.add(travelVO);
        }

        return travelVOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer approveTravelApply(String userId, String approvalId, String status, String travelRejection) {
        // 更新出差申请状态
        Approval approval = this.getApprovalByApprovalId(Integer.parseInt(approvalId));
        // 状态模式的实现，这个是出差申请状态改变
        // TravelApprovalContext travelApprovalContext = new TravelApprovalContext();
        // approval.setAdvanceApproval(travelApprovalContext.getByType(Integer.parseInt(status)).getType());

        approval.setTravelApproval(Integer.parseInt(status));

        if (TravelApprovalEnum.REJECTED.getType() == Integer.parseInt(status)) {
            if (StringTools.isEmpty(travelRejection)) {
                throw new IllegalArgumentException("请填写拒绝原因");
            }
            approval.setTravelRejection(travelRejection);
        }

        int result = this.updateApprovalByApprovalId(approval, Integer.parseInt(approvalId));

        if (0 == result) {
            throw new BusinessException("提交信息失败");
        }

        // 添加审批出差申请记录
        // TravelApproval travelApproval = new TravelApproval();
        // travelApproval.setManagerId(userId);
        // travelApproval.setTravelId(approval.getTravelId());
        // travelApproval.setDate(new Date(System.currentTimeMillis()));
        // 这是用了工厂方法

        TravelApproval travelApproval = TravelApprovalFactory.create(userId, approval.getTravelId());
        // 查询是否已有记录
        TravelApprovalQuery travelApprovalQuery = new TravelApprovalQuery();
        travelApprovalQuery.setTravelId(approval.getTravelId());
        travelApprovalQuery.setManagerId(userId);
        List<TravelApproval> travelApprovalList = travelApprovalMapper.selectList(travelApprovalQuery);

        if (travelApprovalList.isEmpty()) {
            // 无记录，新增
            result = travelApprovalMapper.insert(travelApproval);
        } else {
            // 有记录，更新
            result = travelApprovalMapper.updateByTravelApprovalId(travelApproval,
                    travelApprovalList.get(0).getTravelApprovalId());
        }

        if (result > 0) {

            System.out
                    .println("approveAdvanceApply" + userId + " " + approvalId + " " + status + " " + travelRejection);

            System.out.println("approve.travelApply");
            Map<String, Object> message = new HashMap<>();
            String msg = "经理已批准您的出差申请";
            if (TravelApprovalEnum.REJECTED.getType() == Integer.parseInt(status)) {
                msg = "经理拒绝了您的出差申请";
            }
            message.put("message", msg);
            message.put("status", Integer.parseInt(status));
            message.put("managerId", userId);
            // message.put("userId", approval.getUserId());
            message.put("userId", approval.getUserId());
            String queueName = "approve.travel";
            rabbitTemplate.convertAndSend(queueName, message);
        }

        return result;
    }

    @Override
    public PaginationResultVO<TravelVO> getAdvanceApply(String userId, Integer pageNo, Integer pageSize) {
        List<TravelVO> travelVOList = new ArrayList<>();

        List<AdvanceApprovalEnum> advanceStatuses = List.of(
                AdvanceApprovalEnum.UNPROCESSED,
                AdvanceApprovalEnum.APPROVED,
                AdvanceApprovalEnum.REJECTED,
                AdvanceApprovalEnum.Handled);

        for (AdvanceApprovalEnum status : advanceStatuses) {
            travelVOList.addAll(fetchTravelVOsByAdvanceStatus(status));
        }

        // 去除自己的申请
        travelVOList.removeIf(travelVO -> travelVO.getUserId().equals(userId));

        int count = travelVOList.size();
        int start = (pageNo - 1) * pageSize;
        int end = start + pageSize;
        if (end > count) {
            end = count;
        }
        int totalPage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;

        PaginationResultVO<TravelVO> result = new PaginationResultVO<>(count, pageSize, pageNo, totalPage,
                travelVOList);

        return result;
    }

    private List<TravelVO> fetchTravelVOsByAdvanceStatus(AdvanceApprovalEnum status) {
        List<TravelVO> travelVOList = new ArrayList<>();

        // 查询出差申请状态, 出差已被批准
        ProcessorChain processorChain = new ProcessorChain();
        processorChain.addProcessor(new TravelProcessor());
        // processorChain.addProcessor(new AdvanceProcessor());
        Approval approvalChain = new Approval();
        approvalChain.setTravelApproval(TravelApprovalEnum.APPROVED.getType());
        approvalChain.setAdvanceApproval(status.getType());
        boolean result = processorChain.process(approvalChain, processorChain);
        if (!result) {
            return travelVOList;
        }

        ApprovalQuery approvalQuery = new ApprovalQuery();
        approvalQuery.setTravelApproval(TravelApprovalEnum.APPROVED.getType());
        approvalQuery.setAdvanceApproval(status.getType());

        List<Approval> approvalList = this.findListByParam(approvalQuery);
        Map<Integer, Approval> approvalMap = approvalList.stream()
                .collect(Collectors.toMap(Approval::getTravelId, approval -> approval));

        List<Integer> travelIdList = approvalList.stream().map(Approval::getTravelId).distinct().toList();

        if (travelIdList.isEmpty()) {
            return travelVOList;
        }

        // 获取出差申请和对应的用户信息
        List<Travel> travelList = this.travelClient.getAllTravelsByIdList(travelIdList);
        travelList.sort((o1, o2) -> o1.getApplyDate().compareTo(o2.getApplyDate()));

        List<String> userIdList = travelList.stream().map(Travel::getUserId).distinct().toList();

        List<User> userList = userClient.getAllUsersByIdList(userIdList);
        Map<String, User> userMap = userList.stream()
                .collect(Collectors.toMap(User::getUserId, user -> user));

        for (Travel travel : travelList) {
            TravelVO travelVO = CopyTools.copy(travel, TravelVO.class);

            travelVO.setAdvanceRejection(approvalMap.get(travel.getTravelId()).getAdvanceRejection());
            travelVO.setApprovalId(approvalMap.get(travel.getTravelId()).getApprovalId());

            travelVO.setAdvanceStatus(status.getType().toString());
            travelVO.setAdvanceStatusName(status.getDesc());

            AdvanceApprovalQuery advanceApprovalQuery = new AdvanceApprovalQuery();
            advanceApprovalQuery.setAdvanceId(travel.getTravelId());
            List<AdvanceApproval> advanceApprovalList = advanceApprovalMapper.selectList(advanceApprovalQuery);
            if (advanceApprovalList != null && !advanceApprovalList.isEmpty()
                    && advanceApprovalList.get(0).getPayment().compareTo(BigDecimal.valueOf(0)) > 0) {
                travelVO.setPayment(advanceApprovalList.get(0).getPayment());
            } else {
                travelVO.setPayment(null);
            }

            User user = userMap.get(travel.getUserId());
            travelVO.setUserName(user.getName());
            travelVO.setUserPhone(user.getPhone());
            travelVO.setUserEmail(user.getEmail());
            travelVO.setPosition(user.getPosition());
            travelVO.setBudget(travelVO.getFoodCost().add(travelVO.getHotelCost()).add(travelVO.getTransportCost()));

            travelVOList.add(travelVO);
        }

        return travelVOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer approveAdvanceApply(String userId, String approvalId, String payment, String status,
            String advanceRejection) {
        // 更新出差申请状态
        Approval approval = this.getApprovalByApprovalId(Integer.parseInt(approvalId));
        // 状态模式的实现,这个是预知款的状态模式改变
        // AdvanceApprovalContext advanceApprovalContext = new AdvanceApprovalContext();
        // approval.setAdvanceApproval(advanceApprovalContext.getByType(Integer.parseInt(status)).getType());
        approval.setAdvanceApproval(Integer.parseInt(status));

        if (AdvanceApprovalEnum.REJECTED.getType() == Integer.parseInt(status)) {
            if (StringTools.isEmpty(advanceRejection)) {
                throw new IllegalArgumentException("请填写拒绝原因");
            }
            approval.setAdvanceRejection(advanceRejection);
        }

        int result = this.updateApprovalByApprovalId(approval, Integer.parseInt(approvalId));

        if (0 == result) {
            throw new BusinessException("提交信息失败");
        }

        // 添加审批出差申请记录
        // AdvanceApproval advanceApproval = new AdvanceApproval();
        // advanceApproval.setFinanceId(userId);
        // advanceApproval.setAdvanceId(approval.getTravelId());
        // if (payment != null && !payment.isEmpty()) {
        // advanceApproval.setPayment(new BigDecimal(payment));
        // } else {
        // advanceApproval.setPayment(new BigDecimal(0));
        // }
        // advanceApproval.setDate(new Date(System.currentTimeMillis()));
        // 使用工厂模式创建AdvanceApproval对象

        // 这里用工厂方法
        AdvanceApproval advanceApproval = AdvanceApprovalFactory.create(
                userId,
                approval.getTravelId(),
                payment);

        // 查询是否已有记录
        AdvanceApprovalQuery advanceApprovalQuery = new AdvanceApprovalQuery();
        advanceApprovalQuery.setAdvanceId(approval.getTravelId());
        List<AdvanceApproval> advanceApprovalList = advanceApprovalMapper.selectList(advanceApprovalQuery);
        System.out.println(advanceApprovalList.size());

        if (advanceApprovalList.isEmpty()) {
            // 无记录，新增
            result = this.advanceApprovalMapper.insert(advanceApproval);
        } else {
            // 有记录，更新
            result = this.advanceApprovalMapper.updateByAdvanceApprovalId(advanceApproval,
                    advanceApprovalList.get(0).getAdvanceApprovalId());
        }

        if (result > 0) {
            System.out.println("approve.advanceApply");
            Map<String, Object> message = new HashMap<>();
            String msg = "财务" + userId + "已批准您的预支款申请";
            if (TravelApprovalEnum.REJECTED.getType() == Integer.parseInt(status)) {
                msg = "财务" + userId + "拒绝了您的预支款申请";
            }
            message.put("message", msg);
            message.put("status", Integer.parseInt(status));
            message.put("financeId", userId);
            message.put("userId", approval.getUserId());
            String queueName = "approve.advance";
            rabbitTemplate.convertAndSend(queueName, message);
        }

        return result;
    }

    @Override
    public PaginationResultVO<ReimbursementVO> getReimbursementApplyMa(String userId, Integer pageNo,
            Integer pageSize) {
        List<ReimbursementVO> reimbursementVOList = new ArrayList<>();

        List<ReimbursementApprovalEnum> reimbursementStatuses = List.of(
                ReimbursementApprovalEnum.UNPROCESSED,
                ReimbursementApprovalEnum.APPROVED,
                ReimbursementApprovalEnum.REJECTED);

        for (ReimbursementApprovalEnum status : reimbursementStatuses) {
            reimbursementVOList.addAll(fetchReimbursementVOsByApprovalStatusMa(status));
        }

        // 去除自己的申请
        reimbursementVOList.removeIf(reimbursementVO -> reimbursementVO.getUserId().equals(userId));

        int count = reimbursementVOList.size();
        int start = (pageNo - 1) * pageSize;
        int end = start + pageSize;
        if (end > count) {
            end = count;
        }
        int totalPage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;

        PaginationResultVO<ReimbursementVO> result = new PaginationResultVO<>(count, pageSize, pageNo, totalPage,
                reimbursementVOList);

        return result;
    }

    private List<ReimbursementVO> fetchReimbursementVOsByApprovalStatusMa(ReimbursementApprovalEnum status) {
        List<ReimbursementVO> reimbursementVOList = new ArrayList<>();

        // 查询报销申请状态，出差已被批准
        ProcessorChain processorChain = new ProcessorChain();
        processorChain.addProcessor(new TravelProcessor());
        // processorChain.addProcessor(new AdvanceProcessor());
        Approval approvalChain = new Approval();
        approvalChain.setTravelApproval(TravelApprovalEnum.APPROVED.getType());
        approvalChain.setAdvanceApproval(status.getType());
        boolean result = processorChain.process(approvalChain, processorChain);
        if (!result) {
            return reimbursementVOList;
        }

        ApprovalQuery approvalQuery = new ApprovalQuery();
        approvalQuery.setTravelApproval(TravelApprovalEnum.APPROVED.getType());
        approvalQuery.setReimbursementApprovalMa(status.getType());
        List<Approval> approvalList = this.findListByParam(approvalQuery);
        Map<Integer, Approval> approvalMap = approvalList.stream()
                .collect(Collectors.toMap(Approval::getTravelId, approval -> approval));

        List<Integer> travelIdList = approvalList.stream().map(Approval::getTravelId).distinct().toList();

        if (travelIdList.isEmpty()) {
            return reimbursementVOList;
        }

        // 获取出差申请和对应的用户信息
        List<Travel> travelList = this.travelClient.getAllTravelsByIdList(travelIdList);
        Map<Integer, Travel> travelMap = travelList.stream()
                .collect(Collectors.toMap(Travel::getTravelId, travel -> travel));

        List<String> userIdList = travelList.stream().map(Travel::getUserId).distinct().toList();

        List<User> userList = userClient.getAllUsersByIdList(userIdList);
        Map<String, User> userMap = userList.stream()
                .collect(Collectors.toMap(User::getUserId, user -> user));

        // 获取报销申请信息
        List<Reimbursement> reimbursementList = this.reimbursementClient.getReimbursementByTravelIdList(travelIdList);

        for (Reimbursement reimbursement : reimbursementList) {
            ReimbursementVO reimbursementVO = CopyTools.copy(reimbursement, ReimbursementVO.class);
            reimbursementVO.setReimbursement(reimbursement.getFoodCost().add(reimbursement.getHotelCost())
                    .add(reimbursement.getTransportCost()));

            Travel travel = travelMap.get(reimbursement.getTravelId());
            reimbursementVO.setTravelReason(travel.getTravelReason());
            reimbursementVO.setTravelDetail(travel.getTravelDetail());
            reimbursementVO.setStartDate(travel.getStartDate());
            reimbursementVO.setEndDate(travel.getEndDate());

            User user = userMap.get(travel.getUserId());
            reimbursementVO.setUserId(user.getUserId());
            reimbursementVO.setUserName(user.getName());
            reimbursementVO.setUserPhone(user.getPhone());
            reimbursementVO.setUserEmail(user.getEmail());
            reimbursementVO.setPosition(user.getPosition());

            Approval approval = approvalMap.get(travel.getTravelId());
            reimbursementVO.setApprovalId(approval.getApprovalId());
            reimbursementVO.setReimbursementStatus(status.getType().toString());
            reimbursementVO.setReimbursementStatusName(status.getDesc());
            reimbursementVO.setReimbursementRejection(approval.getReimbursementRejectionMa());

            reimbursementVOList.add(reimbursementVO);
        }

        return reimbursementVOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer approveReimbursementApplyMa(String userId, String reimbursementId, String approvalId, String status,
            String reimbursementRejection) {
        Approval approval = this.getApprovalByApprovalId(Integer.parseInt(approvalId));

        // //状态模式的实现,这个是报销表的经理状态模式改变
        // ReimbursementApprovalContext reimbursementApprovalContext = new
        // ReimbursementApprovalContext();
        // approval.setAdvanceApproval(reimbursementApprovalContext.getByType(Integer.parseInt(status)).getType());

        approval.setReimbursementApprovalMa(Integer.parseInt(status));

        if (ReimbursementApprovalEnum.REJECTED.getType() == Integer.parseInt(status)) {
            if (StringTools.isEmpty(reimbursementRejection)) {
                throw new IllegalArgumentException("请填写拒绝原因");
            }
            approval.setReimbursementRejectionMa(reimbursementRejection);
        }

        int result = this.updateApprovalByApprovalId(approval, Integer.parseInt(approvalId));

        if (0 == result) {
            throw new BusinessException("提交信息失败");
        }

        // ReimbursementApprovalMa reimbursementApprovalMa = new
        // ReimbursementApprovalMa();
        // ReimbursementApprovalMa reimbursementApprovalMa = new
        // ReimbursementApprovalMa();
        // reimbursementApprovalMa.setManagerId(userId);
        // reimbursementApprovalMa.setReimbursementId(Integer.parseInt(reimbursementId));
        // reimbursementApprovalMa.setDate(new Date(System.currentTimeMillis()));

        // 工厂模式实现
        ReimbursementApprovalMa reimbursementApprovalMa = ReimbursementApprovalMaFactory
                .createReimbursementApprovalMa(userId, Integer.parseInt(reimbursementId));

        ReimbursementApprovalMaQuery reimbursementApprovalMaQuery = new ReimbursementApprovalMaQuery();
        reimbursementApprovalMaQuery.setReimbursementApprovalMaId(Integer.parseInt(reimbursementId));
        reimbursementApprovalMaQuery.setManagerId(userId);
        List<ReimbursementApprovalMa> reimbursementApprovalMaList = this.reimbursementApprovalMaMapper
                .selectList(reimbursementApprovalMaQuery);

        if (reimbursementApprovalMaList.isEmpty()) {
            // 无记录，新增
            result = this.reimbursementApprovalMaMapper.insert(reimbursementApprovalMa);
        } else {
            // 有记录，更新
            result = this.reimbursementApprovalMaMapper.updateByReimbursementApprovalMaId(reimbursementApprovalMa,
                    reimbursementApprovalMaList.get(0).getReimbursementApprovalMaId());
        }

        if (result > 0) {
            System.out.println("approve.reimbursementMa");
            Map<String, Object> message = new HashMap<>();
            String msg = "经理已批准您的预支款申请";
            if (TravelApprovalEnum.REJECTED.getType() == Integer.parseInt(status)) {
                msg = "经理拒绝了您的预支款申请";
            }
            message.put("message", msg);
            message.put("status", Integer.parseInt(status));
            message.put("managerId", userId);
            message.put("userId", approval.getUserId());
            String queueName = "approve.reimbursementMa";
            rabbitTemplate.convertAndSend(queueName, message);
        }

        return result;
    }

    @Override
    public PaginationResultVO<ReimbursementVO> getReimbursementApplyFi(String userId, Integer pageNo,
            Integer pageSize) {
        List<ReimbursementVO> reimbursementVOList = new ArrayList<>();

        List<ReimbursementApprovalEnum> reimbursementStatuses = List.of(
                ReimbursementApprovalEnum.UNPROCESSED,
                ReimbursementApprovalEnum.APPROVED,
                ReimbursementApprovalEnum.REJECTED,
                ReimbursementApprovalEnum.Handled);

        for (ReimbursementApprovalEnum status : reimbursementStatuses) {
            reimbursementVOList.addAll(fetchReimbursementVOsByApprovalStatusFi(status));
        }

        // 去除自己的申请
        reimbursementVOList.removeIf(reimbursementVO -> reimbursementVO.getUserId().equals(userId));

        int count = reimbursementVOList.size();
        int start = (pageNo - 1) * pageSize;
        int end = start + pageSize;
        if (end > count) {
            end = count;
        }
        int totalPage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;

        PaginationResultVO<ReimbursementVO> result = new PaginationResultVO<>(count, pageSize, pageNo, totalPage,
                reimbursementVOList);

        return result;
    }

    private List<ReimbursementVO> fetchReimbursementVOsByApprovalStatusFi(ReimbursementApprovalEnum status) {
        List<ReimbursementVO> reimbursementVOList = new ArrayList<>();

        // 查询报销申请状态，出差已被批准，已被经理批准
        ProcessorChain processorChain = new ProcessorChain();
        processorChain.addProcessor(new TravelProcessor());
        processorChain.addProcessor(new ReimbursementMaProcessor());
        Approval approvalChain = new Approval();
        approvalChain.setTravelApproval(TravelApprovalEnum.APPROVED.getType());
        approvalChain.setReimbursementApprovalMa(ReimbursementApprovalEnum.APPROVED.getType());
        approvalChain.setAdvanceApproval(status.getType());
        boolean result = processorChain.process(approvalChain, processorChain);
        if (!result) {
            return reimbursementVOList;
        }

        ApprovalQuery approvalQuery = new ApprovalQuery();
        approvalQuery.setTravelApproval(TravelApprovalEnum.APPROVED.getType());
        approvalQuery.setReimbursementApprovalMa(ReimbursementApprovalEnum.APPROVED.getType());
        approvalQuery.setReimbursementApprovalFi(status.getType());
        List<Approval> approvalList = this.findListByParam(approvalQuery);
        Map<Integer, Approval> approvalMap = approvalList.stream()
                .collect(Collectors.toMap(Approval::getTravelId, approval -> approval));

        List<Integer> travelIdList = approvalList.stream().map(Approval::getTravelId).distinct().toList();

        if (travelIdList.isEmpty()) {
            return reimbursementVOList;
        }

        // 获取出差申请和对应的用户信息
        List<Travel> travelList = this.travelClient.getAllTravelsByIdList(travelIdList);
        Map<Integer, Travel> travelMap = travelList.stream()
                .collect(Collectors.toMap(Travel::getTravelId, travel -> travel));

        List<String> userIdList = travelList.stream().map(Travel::getUserId).distinct().toList();

        List<User> userList = userClient.getAllUsersByIdList(userIdList);
        Map<String, User> userMap = userList.stream()
                .collect(Collectors.toMap(User::getUserId, user -> user));

        // 获取报销申请信息
        List<Reimbursement> reimbursementList = this.reimbursementClient.getReimbursementByTravelIdList(travelIdList);

        for (Reimbursement reimbursement : reimbursementList) {
            ReimbursementVO reimbursementVO = CopyTools.copy(reimbursement, ReimbursementVO.class);
            reimbursementVO.setReimbursement(reimbursement.getFoodCost().add(reimbursement.getHotelCost())
                    .add(reimbursement.getTransportCost()));

            Travel travel = travelMap.get(reimbursement.getTravelId());
            reimbursementVO.setTravelReason(travel.getTravelReason());
            reimbursementVO.setTravelDetail(travel.getTravelDetail());
            reimbursementVO.setStartDate(travel.getStartDate());
            reimbursementVO.setEndDate(travel.getEndDate());

            ReimbursementApprovalFiQuery reimbursementApprovalFiQuery = new ReimbursementApprovalFiQuery();
            reimbursementApprovalFiQuery.setReimbursementId(reimbursement.getReimbursementId());
            List<ReimbursementApprovalFi> reimbursementApprovalFiList = this.reimbursementApprovalFiMapper
                    .selectList(reimbursementApprovalFiQuery);
            if (reimbursementApprovalFiList != null && !reimbursementApprovalFiList.isEmpty()
                    && reimbursementApprovalFiList.get(0).getPayment().compareTo(BigDecimal.valueOf(0)) > 0) {
                reimbursementVO.setPayment(reimbursementApprovalFiList.get(0).getPayment());
            } else {
                reimbursementVO.setPayment(null);
            }

            User user = userMap.get(travel.getUserId());
            reimbursementVO.setUserId(user.getUserId());
            reimbursementVO.setUserName(user.getName());
            reimbursementVO.setUserPhone(user.getPhone());
            reimbursementVO.setUserEmail(user.getEmail());
            reimbursementVO.setPosition(user.getPosition());

            Approval approval = approvalMap.get(travel.getTravelId());
            reimbursementVO.setApprovalId(approval.getApprovalId());
            reimbursementVO.setReimbursementStatus(status.getType().toString());
            reimbursementVO.setReimbursementStatusName(status.getDesc());
            reimbursementVO.setReimbursementRejection(approval.getReimbursementRejectionFi());

            reimbursementVOList.add(reimbursementVO);
        }

        return reimbursementVOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer approveReimbursementApplyFi(String userId, String reimbursementId, String approvalId, String payment,
            String status, String reimbursementRejection) {
        Approval approval = this.getApprovalByApprovalId(Integer.parseInt(approvalId));

        // //状态模式的实现,这个是报销表的财务人员状态模式改变
        // ReimbursementApprovalContext reimbursementApprovalContext = new
        // ReimbursementApprovalContext();
        // approval.setAdvanceApproval(reimbursementApprovalContext.getByType(Integer.parseInt(status)).getType());

        approval.setReimbursementApprovalFi(Integer.parseInt(status));

        if (ReimbursementApprovalEnum.REJECTED.getType() == Integer.parseInt(status)) {
            if (StringTools.isEmpty(reimbursementRejection)) {
                throw new IllegalArgumentException("请填写拒绝原因");
            }
            approval.setReimbursementRejectionFi(reimbursementRejection);
        }

        int result = this.updateApprovalByApprovalId(approval, Integer.parseInt(approvalId));

        if (0 == result) {
            throw new BusinessException("提交信息失败");
        }
        //
        // ReimbursementApprovalFi reimbursementApprovalFi = new
        // ReimbursementApprovalFi();
        // reimbursementApprovalFi.setFinanceId(userId);
        // reimbursementApprovalFi.setReimbursementId(Integer.parseInt(reimbursementId));
        // if (payment != null && !payment.isEmpty()) {
        // reimbursementApprovalFi.setPayment(new BigDecimal(payment));
        // } else {
        // reimbursementApprovalFi.setPayment(new BigDecimal(0));
        // }
        // reimbursementApprovalFi.setDate(new Date(System.currentTimeMillis()));

        // 工厂方法实现
        ReimbursementApprovalFi reimbursementApprovalFi = ReimbursementApprovalFiFactory.create(userId,
                Integer.valueOf(reimbursementId), payment);

        ReimbursementApprovalFiQuery reimbursementApprovalFiQuery = new ReimbursementApprovalFiQuery();
        reimbursementApprovalFiQuery.setReimbursementId(Integer.parseInt(reimbursementId));
        reimbursementApprovalFiQuery.setFinanceId(userId);
        List<ReimbursementApprovalFi> reimbursementApprovalFiList = this.reimbursementApprovalFiMapper
                .selectList(reimbursementApprovalFiQuery);
        System.out.println(reimbursementApprovalFiList.size());

        if (reimbursementApprovalFiList.isEmpty()) {
            // 无记录，新增
            result = this.reimbursementApprovalFiMapper.insert(reimbursementApprovalFi);
        } else {
            // 有记录，更新
            result = this.reimbursementApprovalFiMapper.updateByReimbursementApprovalFiId(reimbursementApprovalFi,
                    reimbursementApprovalFiList.get(0).getReimbursementApprovalFiId());
        }

        if (result > 0) {
            System.out.println("approve.advanceApply");
            Map<String, Object> message = new HashMap<>();
            String msg = "财务" + userId + "已批准您的预支款申请";
            if (TravelApprovalEnum.REJECTED.getType() == Integer.parseInt(status)) {
                msg = "财务" + userId + "拒绝了您的预支款申请";
            }
            message.put("message", msg);
            message.put("status", Integer.parseInt(status));
            message.put("financeId", userId);
            message.put("userId", approval.getUserId());
            String queueName = "approve.reimbursementFi";
            rabbitTemplate.convertAndSend(queueName, message);
        }

        return result;
    }

    /**
     * 根据TravelId查询一个Approval对象
     * 
     * @param travelId
     * @return
     */
    @Override
    public Approval findApprovalByTravelId(Integer travelId) {
        ApprovalQuery approvalQuery = new ApprovalQuery();
        approvalQuery.setTravelId(travelId);
        System.out.println("传到这个approval的travelId是" + travelId);
        Approval approval = this.approvalMapper.selectList(approvalQuery).get(0);
        return approval;
    }

    @Override
    public Approval getApprovalByTravelId(Integer travelId) {
        return this.approvalMapper.selectByTravelId(travelId);
    }
}